﻿/**************************************************************
 * 
 * 唯一标识：65445784-a010-46d5-ad8a-dfb0a4bfd6de
 * 命名空间：Sgr.Threading
 * 创建时间：2024/7/14 21:27:59
 * 机器名称：DESKTOP-HJ4OAG9
 * 创建者：CocoYuan
 * 电子邮箱：fengqinhua2016@163.com
 * 描述：
 * 
 **************************************************************/

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace Sgr.Threading
{
    public static class SemaphoreSlimExtensions
    {
        public async static Task<IDisposable> LockAsync(this SemaphoreSlim semaphoreSlim)
        {
            await semaphoreSlim.WaitAsync();
            return GetDispose(semaphoreSlim);
        }

        public async static Task<IDisposable> LockAsync(this SemaphoreSlim semaphoreSlim, CancellationToken cancellationToken)
        {
            await semaphoreSlim.WaitAsync(cancellationToken);
            return GetDispose(semaphoreSlim);
        }

        public async static Task<IDisposable> LockAsync(this SemaphoreSlim semaphoreSlim, int millisecondsTimeout)
        {
            if (await semaphoreSlim.WaitAsync(millisecondsTimeout))
            {
                return GetDispose(semaphoreSlim);
            }

            throw new TimeoutException();
        }

        public async static Task<IDisposable> LockAsync(this SemaphoreSlim semaphoreSlim, int millisecondsTimeout, CancellationToken cancellationToken)
        {
            if (await semaphoreSlim.WaitAsync(millisecondsTimeout, cancellationToken))
            {
                return GetDispose(semaphoreSlim);
            }

            throw new TimeoutException();
        }

        public async static Task<IDisposable> LockAsync(this SemaphoreSlim semaphoreSlim, TimeSpan timeout)
        {
            if (await semaphoreSlim.WaitAsync(timeout))
            {
                return GetDispose(semaphoreSlim);
            }

            throw new TimeoutException();
        }

        public async static Task<IDisposable> LockAsync(this SemaphoreSlim semaphoreSlim, TimeSpan timeout, CancellationToken cancellationToken)
        {
            if (await semaphoreSlim.WaitAsync(timeout, cancellationToken))
            {
                return GetDispose(semaphoreSlim);
            }

            throw new TimeoutException();
        }

        public static IDisposable Lock(this SemaphoreSlim semaphoreSlim)
        {
            semaphoreSlim.Wait();
            return GetDispose(semaphoreSlim);
        }

        public static IDisposable Lock(this SemaphoreSlim semaphoreSlim, CancellationToken cancellationToken)
        {
            semaphoreSlim.Wait(cancellationToken);
            return GetDispose(semaphoreSlim);
        }

        public static IDisposable Lock(this SemaphoreSlim semaphoreSlim, int millisecondsTimeout)
        {
            if (semaphoreSlim.Wait(millisecondsTimeout))
            {
                return GetDispose(semaphoreSlim);
            }

            throw new TimeoutException();
        }

        public static IDisposable Lock(this SemaphoreSlim semaphoreSlim, int millisecondsTimeout, CancellationToken cancellationToken)
        {
            if (semaphoreSlim.Wait(millisecondsTimeout, cancellationToken))
            {
                return GetDispose(semaphoreSlim);
            }

            throw new TimeoutException();
        }

        public static IDisposable Lock(this SemaphoreSlim semaphoreSlim, TimeSpan timeout)
        {
            if (semaphoreSlim.Wait(timeout))
            {
                return GetDispose(semaphoreSlim);
            }

            throw new TimeoutException();
        }

        public static IDisposable Lock(this SemaphoreSlim semaphoreSlim, TimeSpan timeout, CancellationToken cancellationToken)
        {
            if (semaphoreSlim.Wait(timeout, cancellationToken))
            {
                return GetDispose(semaphoreSlim);
            }

            throw new TimeoutException();
        }

        private static IDisposable GetDispose(this SemaphoreSlim semaphoreSlim)
        {
            return new DisposeAction<SemaphoreSlim>(static (semaphoreSlim) =>
            {
                semaphoreSlim.Release();
            }, semaphoreSlim);
        }
    }

}
